# -*- coding: utf-8 -*-
"""
Excel数据导出模块
从Redis中导出已完成的数据到Excel文件
"""

import pandas as pd
import logging
from typing import List, Dict, Optional
from datetime import datetime
# RedisManager 类型提示（不直接导入，避免循环依赖）
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from .redis_manager import RedisManager

import logging
logger = logging.getLogger(__name__)


class ExcelExporter:
    """Excel数据导出器"""
    
    def __init__(self, redis_manager: 'RedisManager'):
        """初始化Excel导出器"""
        self.redis_manager = redis_manager
    
    def export_to_excel(self, filename: str = None) -> bool:
        """导出数据到Excel文件"""
        try:
            # 获取所有已完成的数据
            completed_data = self.redis_manager.get_all_completed_data()
            
            if not completed_data:
                logger.warning("没有已完成的数据可导出")
                return False
            
            logger.info(f"开始导出 {len(completed_data)} 条数据到Excel")
            
            # 准备数据
            data_list = []
            for item in completed_data:
                data = item.get('data', {})
                data['detail_url'] = item.get('detail_url', '')
                data['category_url'] = item.get('category_url', '')
                data['category_page'] = item.get('category_page', '')
                data['completed_at'] = item.get('completed_at', '')
                data['exported_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                data_list.append(data)
            
            # 创建DataFrame
            df = pd.DataFrame(data_list)
            
            # 生成文件名
            if not filename:
                timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                filename = f"houzz_data_{timestamp}.xlsx"
            
            # 导出到Excel
            with pd.ExcelWriter(filename, engine='openpyxl') as writer:
                # 主数据表
                df.to_excel(writer, sheet_name='专业数据', index=False)
                
                # 统计信息表
                stats_data = self._get_stats_data()
                stats_df = pd.DataFrame(list(stats_data.items()), columns=['统计项', '数量'])
                stats_df.to_excel(writer, sheet_name='统计信息', index=False)
                
                # 类目统计表
                category_stats = self._get_category_stats(df)
                category_df = pd.DataFrame(list(category_stats.items()), columns=['类目', '数量'])
                category_df.to_excel(writer, sheet_name='类目统计', index=False)
            
            logger.info(f"✅ 数据导出成功: {filename}")
            return True
            
        except Exception as e:
            logger.error(f"导出Excel失败: {e}")
            return False
    
    def _get_stats_data(self) -> Dict[str, int]:
        """获取统计信息"""
        stats = self.redis_manager.get_stats()
        return {
            '总数据量': stats.get('completed_data', 0),
            '列表页任务': stats.get('list_tasks', 0),
            '详情页任务': stats.get('detail_tasks', 0),
            '列表页失败任务': stats.get('list_failed_tasks', 0),
            '详情页失败任务': stats.get('detail_failed_tasks', 0)
        }
    
    def _get_category_stats(self, df: pd.DataFrame) -> Dict[str, int]:
        """获取类目统计信息"""
        if 'category_url' in df.columns:
            category_counts = df['category_url'].value_counts().to_dict()
            # 简化类目名称
            simplified_categories = {}
            for url, count in category_counts.items():
                if pd.isna(url):
                    simplified_categories['未知类目'] = count
                else:
                    # 从URL中提取类目名称
                    try:
                        # 使用正则表达式提取类目名称
                        import re
                        pattern = r'/professionals/([^/]+)(?:/|$)'
                        match = re.search(pattern, url)
                        if match:
                            category_name = match.group(1)
                        else:
                            # 备用方法
                            category_name = url.split('/')[-1].split('~')[0] if '~' in url else url.split('/')[-1]
                        simplified_categories[category_name] = count
                    except:
                        simplified_categories[url] = count
            return simplified_categories
        return {}
    
    def export_failed_tasks(self, filename: str = None) -> bool:
        """导出失败任务到Excel"""
        try:
            # 获取失败任务统计
            stats = self.redis_manager.get_stats()
            
            failed_data = []
            
            # 列表页失败任务
            list_failed_count = stats.get('list_failed_tasks', 0)
            if list_failed_count > 0:
                failed_data.append({
                    '任务类型': '列表页任务',
                    '失败数量': list_failed_count,
                    '备注': '需要检查网络连接和代理设置'
                })
            
            # 详情页失败任务
            detail_failed_count = stats.get('detail_failed_tasks', 0)
            if detail_failed_count > 0:
                failed_data.append({
                    '任务类型': '详情页任务',
                    '失败数量': detail_failed_count,
                    '备注': '需要检查网络连接和代理设置'
                })
            
            if not failed_data:
                logger.info("没有失败任务")
                return True
            
            # 创建DataFrame
            df = pd.DataFrame(failed_data)
            
            # 生成文件名
            if not filename:
                timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                filename = f"failed_tasks_{timestamp}.xlsx"
            
            # 导出到Excel
            df.to_excel(filename, index=False)
            logger.info(f"✅ 失败任务导出成功: {filename}")
            return True
            
        except Exception as e:
            logger.error(f"导出失败任务失败: {e}")
            return False
    
    def export_summary_report(self, filename: str = None) -> bool:
        """导出汇总报告"""
        try:
            # 获取统计数据
            stats = self.redis_manager.get_stats()
            completed_data = self.redis_manager.get_all_completed_data()
            
            # 准备报告数据
            report_data = {
                '报告生成时间': [datetime.now().strftime('%Y-%m-%d %H:%M:%S')],
                '总数据量': [stats.get('completed_data', 0)],
                '列表页任务': [stats.get('list_tasks', 0)],
                '详情页任务': [stats.get('detail_tasks', 0)],
                '列表页失败任务': [stats.get('list_failed_tasks', 0)],
                '详情页失败任务': [stats.get('detail_failed_tasks', 0)],
                '成功率': [f"{(stats.get('completed_data', 0) / max(1, stats.get('completed_data', 0) + stats.get('list_failed_tasks', 0) + stats.get('detail_failed_tasks', 0)) * 100):.2f}%"]
            }
            
            # 创建DataFrame
            df = pd.DataFrame(list(report_data.items()), columns=['项目', '值'])
            
            # 生成文件名
            if not filename:
                timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                filename = f"summary_report_{timestamp}.xlsx"
            
            # 导出到Excel
            with pd.ExcelWriter(filename, engine='openpyxl') as writer:
                # 汇总报告
                df.to_excel(writer, sheet_name='汇总报告', index=False)
                
                # 如果有数据，添加数据样本
                if completed_data:
                    sample_data = []
                    for item in completed_data[:10]:  # 只显示前10条作为样本
                        data = item.get('data', {})
                        sample_data.append({
                            '公司名称': data.get('company_name', ''),
                            '公司URL': data.get('company_profile_url', ''),
                            '评分': data.get('average_rating', ''),
                            '评论数': data.get('number_of_reviews', 0),
                            '位置': data.get('location', ''),
                            '类目URL': item.get('category_url', ''),
                            '类目页码': item.get('category_page', '')
                        })
                    
                    sample_df = pd.DataFrame(sample_data)
                    sample_df.to_excel(writer, sheet_name='数据样本', index=False)
            
            logger.info(f"✅ 汇总报告导出成功: {filename}")
            return True
            
        except Exception as e:
            logger.error(f"导出汇总报告失败: {e}")
            return False
